using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Text;
using System.Xml;
using Graffiti.Core;
using System.Web;

namespace Graffiti.Slide.Show
{
    /// <summary>
    /// Slide.Show Photo Gallery
    /// </summary>
    public class FileSystemSlideShowPlugin : GraffitiEvent
    {

        #region Properties

        private string _width = "100%";
        public string Width
        {
            get { return _width; }
            set { _width = value; }
        }

        private string _height = "300";
        public string Height
        {
            get { return _height; }
            set { _height = value; }
        }

        private bool _createThumbnails = true;
        public bool CreateThumbnails
        {
            get { return _createThumbnails; }
            set { _createThumbnails = value; }
        }

        private string _photoDataLocation = string.Empty;
        public string PhotoDataLocation
        {
            get { return _photoDataLocation; }
            set { _photoDataLocation = value; }
        }

        private string _dataFileUrl = string.Empty;
        public string DataFileUrl
        {
            get { return _dataFileUrl; }
            set { _dataFileUrl = value; }
        }

        private int _startAlbum = -1;
        public int StartAlbum
        {
            get { return _startAlbum; }
            set { _startAlbum = value; }
        }

        private string _slideTransition = "CrossFadeTransition";
        public string SlideTransition
        {
            get { return _slideTransition; }
            set { _slideTransition = value; }
        }

        private string _postName = string.Empty;
        public string PostName
        {
            get { return _postName; }
            set { _postName = value; }
        }

        private string _modulesXML = string.Empty;
        public string ModulesXML
        {
            get { return _modulesXML; }
            set { _modulesXML = value; }
        }

        #endregion

        #region Constructor
        public FileSystemSlideShowPlugin()
        {

            this.ModulesXML = PluginHelper.defaultModulesXML;
        }
        #endregion

        #region Init
        public override void Init(GraffitiApplication ga)
        {
            ga.BeginRequest += new EventHandler(ga_BeginRequest);
            ga.RenderHtmlHeader += new RenderContentEventHandler(ga_RenderHtmlHeader);
            ga.RenderPostBody += new RenderPostBodyEventHandler(ga_RenderPostBody);

        }

        #endregion

        #region GraffitiEvent Properties

        public override bool IsEditable
        {
            get { return true; }
        }

        public override string Name
        {
            get { return "Slide.Show Photo Gallery Plugin"; }
        }

        public override string Description
        {
            get
            {
                return "Adds a photo gallery to a post page using the Slide.Show Silverlight component.";
            }
        }

        #endregion

        #region Events

        protected void ga_BeginRequest(object sender, EventArgs e)
        {
            HttpApplication app = sender as HttpApplication;
            HttpContext context = app.Context;
            string path = context.Request.Path.ToLower();

            if (path.Contains("/slideshowplugin-fs-config.aspx"))
            {
                HandleConfigRequest(context);
                return;
            }
            else if (path.Contains("/slideshowplugin-fs-data.aspx"))
            {
                FolderDataHandler folderData = new FolderDataHandler(context, PhotoDataLocation, StartAlbum, SlideTransition);
                folderData.ProcessRequest();
                return;
            }
        }

        protected void ga_RenderHtmlHeader(StringBuilder sb, EventArgs e)
        {
            PluginHelper.RenderSlideShowScript(sb, HttpContext.Current.Handler as TemplatedThemePage, PostName);
        }

        protected void ga_RenderPostBody(StringBuilder sb, PostEventArgs e)
        {
            if (e.RenderLocation == PostRenderLocation.Web && e.Post.Name.ToLower() == PostName.ToLower())
            {
                Macros macros = new Macros();
                sb.Append("\n<script type=\"text/javascript\">\n");
                sb.Append("new SlideShow.Control(new SlideShow.XmlConfigProvider({url:\"");
                sb.Append(macros.FullUrl(VirtualPathUtility.ToAbsolute("~/slideshowplugin-fs-config.aspx")));
                sb.Append("?r=").Append(DateTime.Now.Minute).Append(DateTime.Now.Second);  // Adds some randomness
                sb.Append("\"}));\n");
                sb.Append("</script>\n");
            }
        }

        #endregion

        #region Configuration

        protected override FormElementCollection AddFormElements()
        {
            FormElementCollection fec = new FormElementCollection();
            fec.Add(new MessageElement("intro", "<strong>Slide.Show Photo Gallery</strong>",
                "<a href=\"http://kevinharder.com/downloads/graffiti/slide-show-plugin/\">Click here</a> for more help &amp; info."));

            fec.Add(new MessageElement("photoLocationHeader", "<strong>Setup Instructions</strong><br />Create a new folder inside your site to be the photo gallery root. Inside of it, create subfolders for each album that you want. Put the image files in the album folders. If you want album descriptions, create a plain text file called album.txt inside each album folder that contains that album's description.", null));
            fec.Add(new TextFormElement("photoDataLocation", "Location of photo gallery folder", "Enter the path to the photo gallery root (the folder that contains your albums). It can be absolute (c:\\website\\photos) or relative starting with a tilde (~/photos)."));
            
            // Thumbnail support temporarily removed
            //fec.Add(new CheckFormElement("createThumbnails", "Create thumbnail images", "This plugin will look for thumbnail versions of the images in a <i>thumbnails</i> subfolder of each album. If checked, thumbnails will be created automatically if they don't already exist.", true));

            PluginHelper.AddOptionFormElements(fec);
            fec.Add(new TextFormElement("dataFileUrl", "Custom XML Data File URL", "You can create your own data.xml file that contains albums, image file paths, and descriptions. Enter the full URL to the data.xml file here. It will be used instead of looking in the folder location above."));

            fec.Add(new MessageElement("about", "<br /><strong>About this plugin</strong>",
            "This plugin uses the open source <a href=\"http://www.codeplex.com/SlideShow\">Slide.Show</a> gallery control, which uses <a href=\"http://www.microsoft.com/silverlight/default.aspx\">Microsoft Silverlight 2.0</a> to render. Graffiti plugin written by <a href=\"http://kevinharder.com\">Kevin Harder</a>."));

            return fec;
        }

        protected override NameValueCollection DataAsNameValueCollection()
        {
            NameValueCollection nvc = new NameValueCollection();
            nvc["photoDataLocation"] = PhotoDataLocation;
            nvc["postName"] = PostName;
            nvc["width"] = Width.ToString();
            nvc["height"] = Height.ToString();

            if (StartAlbum < 0)
                nvc["startAlbum"] = string.Empty;
            else
                nvc["startAlbum"] = StartAlbum.ToString();

            nvc["dataFileUrl"] = DataFileUrl;
            nvc["slideTransition"] = SlideTransition;
            nvc["modulesXML"] = ModulesXML;
            //nvc["createThumbnails"] = CreateThumbnails.ToString();

            return nvc;
        }

        public override StatusType SetValues(System.Web.HttpContext context, NameValueCollection nvc)
        {
            if (string.IsNullOrEmpty(nvc["photoDataLocation"]) && string.IsNullOrEmpty(nvc["dataFileUrl"]))
            {
                SetMessage(context, "You forgot to enter the path to the root photo gallery folder.");
                return StatusType.Error;
            }
            if (!string.IsNullOrEmpty(nvc["photoDataLocation"]) && !string.IsNullOrEmpty(nvc["dataFileUrl"]))
            {
                SetMessage(context, "You entered both a photo gallery ");
                return StatusType.Error;
            }

            Data data = new Data();
            PhotoDataLocation = nvc["photoDataLocation"];
            Width = nvc["width"];
            Height = nvc["height"];
            PostName = nvc["postName"];
            Post post = data.GetPost(PostName);
            if (post == null)
            {
                PostName = Util.CleanForUrl(PostName);
                post = data.GetPost(PostName);

                if (post == null)
                {
                    SetMessage(context, "Could not find a post with that post name.");
                    return StatusType.Error;
                }
            }

            try
            {
                if (!string.IsNullOrEmpty(nvc["startAlbum"]))
                    StartAlbum = int.Parse(nvc["startAlbum"]);
                else
                    StartAlbum = -1;
            }
            catch
            {
                StartAlbum = -1;
            }

            DataFileUrl = nvc["dataFileUrl"];
            SlideTransition = nvc["slideTransition"];
            //CreateThumbnails = PluginHelper.ConvertStringToBool(nvc["createThumbnails"]);
            ModulesXML = nvc["modulesXML"];

            return StatusType.Success;
        }

        #endregion

        #region protected void HandleConfigRequest(HttpContext context)
        protected void HandleConfigRequest(HttpContext context)
        {
            Macros macros = new Macros();

            context.Response.Clear();
            context.Response.Cache.SetCacheability(HttpCacheability.Public);

            StringWriter sw = new StringWriter();
            sw.WriteLine("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
            XmlTextWriter writer = new XmlTextWriter(sw);

            writer.WriteStartElement("configuration");
            writer.WriteAttributeString("width", this.Width);
            writer.WriteAttributeString("height", this.Height);

            writer.WriteStartElement("modules");
            if (this.ModulesXML.Trim().Length == 0)
                writer.WriteRaw(PluginHelper.defaultModulesXML);
            else
                writer.WriteRaw(this.ModulesXML);
            writer.WriteEndElement(); // End Modules

            writer.WriteStartElement("transitions");
            writer.WriteRaw(PluginHelper.RenderTransition(this.SlideTransition));
            writer.WriteEndElement(); // End Transitions

            writer.WriteStartElement("dataProvider");
            writer.WriteAttributeString("type", "XmlDataProvider");
            writer.WriteStartElement("option");
            writer.WriteAttributeString("name", "url");

            if (string.IsNullOrEmpty(this.DataFileUrl))
                writer.WriteAttributeString("value", macros.FullUrl(VirtualPathUtility.ToAbsolute("~/slideshowplugin-fs-data.aspx")) + "?r=" + DateTime.Now.Minute.ToString() + DateTime.Now.Second.ToString());
            else
                writer.WriteAttributeString("value", this.DataFileUrl);

            writer.WriteEndElement(); // End option
            writer.WriteEndElement(); // End dataProvider
            writer.WriteEndElement(); // End configuration

            // save XML into response
            context.Response.ContentEncoding = System.Text.Encoding.UTF8;
            context.Response.ContentType = "text/xml";
            context.Response.Write(sw.ToString());
            context.Response.End();
        }

        #endregion

    }
}
